home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / C Internet Config / IC Component Debug ƒ / IC Component Source ƒ / 68k Version ƒ / IC Link In.c < prev    next >
Encoding:
Text File  |  1995-12-06  |  37.0 KB  |  1,084 lines  |  [TEXT/SPM ]

  1. fs->vRefNum,&fs->parID,&eric);
  2.             BlockMoveData(oreply.fName,fs->name,oreply.fName[0]+1);
  3.         }
  4.     }
  5.     
  6.     return err;
  7. }
  8.  
  9. ICError PutFile(ICRRecord* inst,FSSpecPtr fs){
  10.     ICError err;
  11.     SFTypeList typeList;
  12.     StandardFileReply nreply;
  13.     SFReply oreply;
  14.     long eric;
  15.     Str63 defname;
  16.     
  17.     SetSFCWD(inst);
  18.     err=userCanceledErr;
  19.     typeList[0]=kICFileType;
  20.     
  21.     if (inst->have_config_file){
  22.         BlockMoveData(inst->config_file.name,defname,inst->config_file.name[0]+1);
  23.     } else {
  24.         BlockMoveData(inst->default_filename,defname,inst->default_filename[0]+1);
  25.     }
  26.     
  27.     if (HaveNewStandardFile()){
  28.         StandardPutFile(inst->prompt,defname,&nreply);
  29.         if (nreply.sfGood){
  30.             BlockMoveData((Ptr)&(nreply.sfFile),(Ptr)fs,sizeof(FSSpec));
  31.             err=noErr;
  32.         }
  33.     } else {
  34.         Point where;
  35.         
  36.         where.h=0x040;
  37.         where.v=0x040;
  38.         
  39.         SFPutFile(where,inst->prompt,defname,(DlgHookUPP)0,&oreply);
  40.         if (oreply.good){
  41.             err=GetWDInfo(oreply.vRefNum,&fs->vRefNum,&fs->parID,&eric);
  42.             BlockMoveData(oreply.fName,fs->name,oreply.fName[0]+1);
  43.         }
  44.     }
  45.     
  46.     return err;
  47. }
  48.  
  49. ICError ICRChooseConfig(ICRRecord* inst){
  50.     OSErr err=noErr;
  51.     FSSpec config;
  52.     
  53.     if (inst->perm!=icNoPerm)
  54.         return paramErr;
  55.     
  56.     err=CanInteract();
  57.     
  58.     if (err==noErr){
  59.         err=GetFile(inst,&config);
  60.     }
  61.     
  62.     if (err==noErr){
  63.         err=ICRSpecifyConfigFile(inst,&config);
  64.     }
  65.     
  66.     return err;
  67. }
  68.  
  69. ICError ICRChooseNewConfig(ICRRecord* inst){
  70.     OSErr err=noErr;
  71.     FSSpec config;
  72.     
  73.     if (inst->perm!=icNoPerm)
  74.         return paramErr;
  75.     
  76.     err=CanInteract();
  77.     
  78.     if (err==noErr)
  79.         err=PutFile(inst,&config);
  80.     
  81.     if (err==noErr){
  82.         HDelete(config.vRefNum,config.parID,config.name);
  83.         err=HCreate(config.vRefNum,config.parID,config.name,kICCreator,kICFileType);
  84.     }
  85.     
  86.     if (err==noErr)
  87.         err=ICRSpecifyConfigFile(inst,&config);
  88.     
  89.     return err;
  90. }
  91.  
  92. ICError ICRGetConfigName(ICRRecord* inst,Boolean longname,StringPtr name){
  93.     OSErr err=noErr;
  94.     
  95.     if (!inst->have_config_file)
  96.         return paramErr;
  97.     
  98.     if (!longname){
  99.         BlockMoveData(inst->config_file.name,name,inst->config_file.name[0]+1);
  100.         err=noErr;
  101.     } else {
  102.         err=FSSpecToFullPath(&(inst->config_file),name);
  103.     }
  104.     
  105.     return err;
  106. }
  107.  
  108. ICError ICRGetConfigReference(ICRRecord* inst,ICConfigRefHandle ref){
  109.     ICError err=noErr;
  110.     ICConfigRef header;
  111.     long loe;
  112.     
  113.     if (!inst->have_config_file)
  114.         return paramErr;
  115.     
  116.     if (ref==(ICConfigRefHandle)0)
  117.         return paramErr;
  118.     
  119.     err=FSSpecToICFileSpec(&(inst->config_file),(ICFileSpecHandle)ref);
  120.     
  121.     if (err==noErr){
  122.         header.manufacturer=kICOurManufacturer;
  123.         loe=Munger((Handle)ref,0,(Ptr)0,0,&header,sizeof(ICConfigRef));
  124.         err=MemError();
  125.     }
  126.     
  127.     if (err!=noErr)
  128.         SetHandleSize((Handle)ref,0);
  129.     
  130.     return err;
  131. }
  132.  
  133. ICError ICRSetConfigReference(ICRRecord* inst,ICConfigRefHandle ref,long flags){
  134.     ICError err;
  135.     ICFileSpecHandle filespec;
  136.     long loe;
  137.     FSSpec fs;
  138.     
  139.     if (inst->perm!=icNoPerm)
  140.         return paramErr;
  141.     
  142.     if (ref==(ICConfigRefHandle)0)
  143.         return paramErr;
  144.     
  145.     if (GetHandleSize((Handle)ref)<4)
  146.         return paramErr;
  147.     
  148.     if ((*ref)->manufacturer!=kICOurManufacturer)
  149.         return icConfigInappropriateErr;
  150.     
  151.     if (GetHandleSize((Handle)ref)<(sizeof(ICConfigRef)+sizeof(ICFileSpec)))
  152.         return paramErr;
  153.     
  154.     BlockMoveData((Ptr)ref,(Ptr)&filespec,sizeof(ICFileSpecHandle));
  155.     err=HandToHand((Handle*)(&filespec));
  156.     
  157.     if (err==noErr){
  158.         loe=Munger((Handle)filespec,0,(Ptr)0,sizeof(ICConfigRef),&loe,0);
  159.         err=ICFileSpecToFSSpec(filespec,!(flags&icNoUserInteraction_mask),&fs);
  160.         DisposeHandle((Handle)filespec);
  161.     }
  162.     
  163.     if (err==noErr)
  164.         ICRSpecifyConfigFile(inst,&fs);
  165.     
  166.     return err;
  167. }
  168.  
  169. ICError ICRSpecifyConfigFile(ICRRecord* inst,FSSpecPtr config){
  170.     ICError err;
  171.     ICDirSpec folder;
  172.     
  173.     if (inst->perm!=icNoPerm)
  174.         return paramErr;
  175.     
  176.     folder.vRefNum=config->vRefNum;
  177.     folder.dirID=config->parID;
  178.     
  179.     err=ValidDirSpec(&folder);
  180.     
  181.     if (err==noErr)
  182.         BlockMoveData((Ptr)config,(Ptr)&(inst->config_file),sizeof(FSSpec));
  183.     
  184.     inst->have_config_file=(err==noErr);
  185.     
  186.     if (inst->have_config_file){
  187.         // Need to ensure that there is a resource fork for a file...
  188.         err=EnsureResourceFork(&(inst->config_file));
  189.     }
  190.     
  191.     return err;
  192. }
  193.  
  194. ICError ICRGetSeed(ICRRecord* inst,long* seed){
  195.     ICError err;
  196.     CInfoPBRec cpb;
  197.     
  198.     *seed=0L;
  199.     err=fnfErr;
  200.     
  201.     if (inst->have_confih=(Handle)0;
  202.             }
  203.             if (prefh==(Handle)0)
  204.                 old_attr=0;
  205.             else
  206.                 old_attr=**((long**)prefh);
  207.             
  208.             if (attr==ICattr_no_change)
  209.                 attr=old_attr;
  210.             
  211.             if ((old_attr&ICattr_locked_mask)&&(attr&ICattr_locked_mask)&&(buf!=(Ptr)0))
  212.                 err=icPermErr;
  213.             
  214.             if (prefh==(Handle)0){
  215.                 prefh=NewHandle(size+4);
  216.                 err=MemError();
  217.                 
  218.                 if (err==noErr){
  219.                     do {
  220.                         id=Unique1ID(kRes_Code);
  221.                     } while (id<=127);
  222.                     
  223.                     AddResource(prefh,kRes_Code,id,key);
  224.                     err=ResError();
  225.                     
  226.                     if (err!=noErr){
  227.                         DisposeHandle(prefh);
  228.                         prefh=(Handle)0;
  229.                     }
  230.                 }
  231.             }
  232.             if ((err==noErr)&&(buf!=(Ptr)0)){
  233.                 SetHandleSize(prefh,size+4);
  234.                 err=MemError();
  235.             }
  236.             if ((err==noErr)&&(size>0))
  237.                 BlockMoveData(buf,(Ptr)((*prefh)+4),size);
  238.             if (err==noErr){
  239.                 **((long**)prefh)=attr;
  240.                 ChangedResource(prefh);
  241.                 WriteResource(prefh);
  242.                 err=ResError();
  243.             }
  244.             UseResFile(old_refnum);
  245.         }
  246.     }
  247.     
  248.     if (prefh!=(Handle)0)
  249.         ReleaseResource(prefh);
  250.     
  251.     err2=ICRReleaseInside(inst,force_info);
  252.     
  253.     if (err==noErr)
  254.         err=err2;
  255.     
  256.     return err;
  257. }
  258.  
  259. // I call ICRForceInside to speed this routine up.  ICRForceInside will do an ICRBegin and hence open the resource
  260. // file, which is good because otherwise I'd open it twice, once for each ICRGetPref.
  261.  
  262. ICError ICRFindPrefHandle(ICRRecord* inst,StringPtr key,ICAttr* attr,Handle prefh){
  263.     ICError err=noErr,err2=noErr;
  264.     long prefsize=0L;
  265.     Boolean force_info;
  266.     
  267.     if (prefh==(Handle)0)
  268.         err=paramErr;
  269.     
  270.     if (err==noErr){
  271.         err=ICRForceInside(inst,icReadOnlyPerm,&force_info);
  272.         if (err==noErr)
  273.             err=ICRGetPref(inst,key,attr,(Ptr)0,&prefsize);
  274.         
  275.         if (err==noErr){
  276.             SetHandleSize(prefh,prefsize);
  277.             err=MemError();
  278.         }
  279.         
  280.         if (err==noErr){
  281.             HLock(prefh);
  282.             err=ICRGetPref(inst,key,attr,*prefh,&prefsize);
  283.             HUnlock(prefh);
  284.         }
  285.         
  286.         err2=ICRReleaseInside(inst,force_info);
  287.     }
  288.     if (err==noErr)
  289.         err=err2;
  290.     
  291.     if ((prefh!=(Handle)0)&&(err!=noErr)){
  292.         SetHandleSize(prefh,0);
  293.     }
  294.     
  295.     return err;
  296. }
  297.  
  298. ICError ICRGetPrefHandle(ICRRecord* inst,StringPtr key,ICAttr* attr,Handle* prefh){
  299.     ICError err;
  300.     
  301.     *prefh=NewHandle(0);
  302.     err=MemError();
  303.     
  304.     if (err==noErr)
  305.         err=ICRFindPrefHandle(inst,key,attr,*prefh);
  306.     
  307.     if (err==icPrefNotFoundErr){
  308.         SetHandleSize(*prefh,0);
  309.         *attr=0;
  310.         err=noErr;
  311.     }
  312.     
  313.     return err;
  314. }
  315.  
  316. ICError ICRSetPrefHandle(ICRRecord* inst,StringPtr key,ICAttr attr,Handle prefh){
  317.     ICError err=noErr;
  318.     SignedByte s;
  319.     
  320.     if (prefh!=(Handle)0){
  321.         if (*prefh==(Ptr)0)
  322.             err=paramErr;
  323.         if (err==noErr){
  324.             s=HGetState(prefh);
  325.             HLock(prefh);
  326.             err=ICRSetPref(inst,key,attr,*prefh,GetHandleSize(prefh));
  327.             HSetState(prefh,s);
  328.         }
  329.     } else {
  330.         err=ICRSetPref(inst,key,attr,(Ptr)0,0);
  331.     }
  332.     
  333.     return err;
  334. }
  335.  
  336. ICError ICRCountPref(ICRRecord* inst,long* count){
  337.     ICError err;
  338.     short old_refnum;
  339.     
  340.     err=ICRCheckInside(inst);
  341.     if (err==noErr){
  342.         if (inst->config_refnum==0)
  343.             *count=0;
  344.         else {
  345.             old_refnum=CurResFile();
  346.             UseResFile(inst->config_refnum);
  347.             err=ResError();
  348.             if (err==noErr){
  349.                 *count=Count1Resources(kRes_Code);
  350.                 err=ResError();
  351.                 UseResFile(old_refnum);
  352.             }
  353.         }
  354.     }
  355.     
  356.     if (err!=noErr)
  357.         *count=0;
  358.     
  359.     return err;
  360. }
  361.  
  362. ICError ICRGetIndPref(ICRRecord* inst,long n,StringPtr key){
  363.     ICError err;
  364.     short old_refnum;
  365.     Handle prefh=(Handle)0;
  366.     short junk_id;
  367.     ResType junk_type;
  368.     
  369.     err=ICRCheckInside(inst);
  370.     if ((err==noErr)&&(n<1))
  371.         err=paramErr;
  372.     
  373.     if (err==noErr){
  374.         if (inst->config_refnum==0)
  375.             err=icPrefNotFoundErr;
  376.         else {
  377.             old_refnum=CurResFile();
  378.             UseResFile(inst->config_refnum);
  379.             err=ResError();
  380.             if (err==noErr){
  381.                 SetResLoad(false);
  382.                 prefh=Get1IndResource(kRes_Code,n);
  383.                 SetResLoad(true);
  384.                 
  385.                 if (prefh==(Handle)0)
  386.                     err=icPrefNotFoundErr;
  387.                 else {
  388.                     GetResInfo(prefh,&junk_id,&junk_type,key);
  389.                     err=ResError();
  390.                 }
  391.                 UseResFile(old_refnum);
  392.             }
  393.         }
  394.     }
  395.     
  396.     if (prefh!=(Handle)0)
  397.         ReleaseResource(prefh);
  398.     
  399.     return err;
  400. }
  401.  
  402. ICError ICRDeletePref(ICRRecord* inst,StringPtr key){
  403.     ICError err;
  404.     Handle prefh;
  405.     short old_refnum;
  406.     
  407.     err=ICRCheckInside(inst);
  408.     if ((err==noErr)&&(key[0]==0))
  409.         err=paramErr;
  410.     
  411.     if (err==noErr){
  412.         if (inst->config_refnum==0)
  413.             err=icPrefNotFoundErr;
  414.         else {
  415.             old_refnum=CurResFile();
  416.             UseResFile(inst->config_refnum);
  417.             err=ResError();
  418.             if (err==noErr){
  419.                 SetResLoad(false);
  420.                 prefh=Get1NamedResource(kRes_Code,key);
  421.                 err=ResError();
  422.                 SetResLoad(true);
  423.                 if (prefh==(Handle)0)
  424.                     err=icPrefNotFoundErr;
  425.                 else {
  426.                     RmveResource(prefh);
  427.                     DisposeHandle(prefh);
  428.                     err=ResError();
  429.                 }
  430.                 UseResFile(old_refnum);
  431.             }
  432.         }
  433.     }
  434.     
  435.     return err;
  436. }
  437.  
  438. ICError ICREnd(ICRRecord* inst){
  439.     ICError err;
  440.     
  441.     err=ICRCheckInside(inst);
  442.     ICRCloseIfOpen(inst);
  443.     
  444.     return err;
  445. }
  446.  
  447. ICError ICRDefaultFileName(ICRRecord* inst,StringPtr name){
  448.     Str63 lname=kICDefaultFileName;
  449.     
  450.     BlockMoveData(lname,name,lname[0]+1);
  451.     
  452.     return noErr;
  453. }
  454.  
  455. ICError ICREditPreferences(ICRRecord* inst,StringPtr key){
  456.     ICError err;
  457.     
  458.     if (!inst->have_config_file)
  459.         return bdNamErr;
  460.     
  461.     return EditPreferences(key,&(inst->config_file));
  462. }
  463.  
  464. /*
  465.     URL Parsing Algorithm
  466.  
  467.     1. if there is a selection skip to step 4
  468.     2. expand selection to end of word (never skip an angle bracket though)
  469.     3. if either end has an angle bracket then expand other end to search for angle bracket
  470.     4. strip trailing and leading whitespace
  471.     5. strip whitespace CR whitespace
  472.     6. off < > if necessary
  473.     7. remove leading URL:
  474.     8. extract protocol by looking forwards for :
  475.     9. if no protocol then prepend "hint:"
  476. */
  477.  
  478. Boolean __URL_SpecStartChar(char ch){
  479.     switch (ch){
  480.         case ' ':
  481.         case '<':
  482.         case 9:
  483.         case 13:
  484.             return true;
  485.         default:
  486.             return false;
  487.     }
  488. }
  489.  
  490. Boolean __URL_SpecEndChar(char ch){
  491.     switch (ch){
  492.         case ' ':
  493.         case '>':
  494.         case 9:
  495.         case 13:
  496.             return true;
  497.         default:
  498.             return false;
  499.     }
  500. }
  501.  
  502. ICError ExpandSelection(char* datap,long len,long* selStart,long* selEnd){
  503.     ICError err=noErr;
  504.     Boolean found;
  505.     
  506.     // expand leading selection backwards looking for word break
  507.     while ((*selStart>0)&&(!__URL_SpecStartChar(datap[(*selStart)-1])))
  508.         (*selStart)--;
  509.     if ((*selStart>0)&&(datap[(*selStart)-1]=='<'))
  510.         (*selStart)--;
  511.     
  512.     // expand trailing selection forwards looking for word break
  513.     while ((*selEnd<len)&&(!__URL_SpecEndChar(datap[*selEnd])))
  514.         (*selEnd)++;
  515.     if ((*selEnd<len)&&(datap[*selEnd]=='>'))
  516.         (*selEnd)++;
  517.     
  518.     // if first char was a < then expand trailing selection to meet matching >
  519.     if ((datap[*selStart]=='<')&&(datap[(*selEnd)-1]!='>')){
  520.         while ((datap[(*selEnd)-1]!='>')&&((*selEnd)-1<=len))
  521.             (*selEnd)++;
  522.         
  523.         // now either a match or at end of len
  524.         if (datap[(*selEnd)-1]!='>')
  525.             return icNoURLErr;
  526.     }
  527.     
  528.     // if last char was a > then expand leading selection to meet matching <
  529.     if ((datap[*selEnd]=='>')&&(datap[*selStart]!='<')){
  530.         while ((datap[*selStart]!='<')&&(*selStart>=0))
  531.             (*selStart)--;
  532.         
  533.         // now either a match or at end of len
  534.         if (datap[*selStart]!='<')
  535.             return icNoURLErr;
  536.     }
  537.     
  538.     return err;
  539. }
  540.  
  541. Boolean SpaceTab(char ch){
  542.     if ((ch==' ')||(ch==9))
  543.         return true;
  544.     return false;
  545. }
  546.  
  547. Boolean SpaceTabRet(char ch){
  548.     if (ch==13)
  549.         return true;
  550.     return SpaceTab(ch);
  551. }
  552.  
  553. ICError ShrinkSelection(char* datap,long len,long* selStart,long* selEnd){
  554.     if (SpaceTab(datap[*selStart]))
  555.         while (SpaceTab(datap[*selStart]))
  556.             (*selStart)++;
  557.     if (SpaceTab(datap[(*selEnd)-1]))
  558.         while (SpaceTab(datap[(*selEnd)-1]))
  559.             (*selEnd)--;
  560.     
  561.     return noErr;
  562. }
  563.  
  564. ICError StripReturns(Handle urlh){
  565.     ICError err;
  566.     long srcsize,srcndx,dstndx;
  567.     char* buf;
  568.     SignedByte s;
  569.     
  570.     srcsize=GetHandleSize(urlh);
  571.     err=MemError();
  572.     if (srcsize==0){
  573.         if (err!=noErr)
  574.             return err;
  575.         
  576.         return icNoURLErr;
  577.     }
  578.     
  579.     srcndx=0;
  580.     dstndx=0;
  581.     
  582.     s=HGetState(urlh);
  583.     HLock(urlh);
  584.     buf=(char*)(*urlh);
  585.     
  586.     // skip down the buffer copying src to dst except when meeting cr
  587.     while (srcndx<srcsize){
  588.         if (buf[srcndx]==13){
  589.             // move dstndx back to point to previous non-whitespace
  590.             while ((dstndx>0)&&(SpaceTab(buf[dstndx-1])))
  591.                 dstndx--;
  592.             // move srcndx forwards to next non-whitespace
  593.             while ((srcndx<srcsize)&&(SpaceTabRet(buf[srcndx])))
  594.                 srcndx++;
  595.         }
  596.         
  597.         if (srcndx<srcsize){
  598.             // copy byte from src to dest
  599.             buf[dstndx]=buf[srcndx];
  600.             srcndx++;
  601.             dstndx++;
  602.         }
  603.     }
  604.     
  605.     HSetState(urlh,s);
  606.     
  607.     // resize the handle to the number of bytes that we copied
  608.     SetHandleSize(urlh,dstndx);
  609.     err=MemError();
  610.     
  611.     return err;
  612. }
  613.  
  614. ICError ICRParseURL(ICRRecord* inst,StringPtr hint,Ptr data,long len,long* selStart,long* selEnd,Handle urlh){
  615.     char* datap=(char*)data;
  616.     Str31 tmp="\pURL:";
  617.     long junklong;
  618.     long ndx;
  619.     ICError err=noErr;
  620.     
  621.     if ((data==(Ptr)0)||(urlh==(Handle)0)||(*urlh==(Ptr)0)||(len<=0)||(*selStart<0)||(*selEnd<0)||(*selStart>len)||(*selEnd>len)||(*selStart>*selEnd))
  622.         return paramErr;
  623.     
  624.     if (*selStart==*selEnd)
  625.         err=ExpandSelection(datap,len,selStart,selEnd);
  626.     if (err==noErr) // remove leading and trailing whitespace
  627.         err=ShrinkSelection(datap,len,selStart,selEnd);
  628.     
  629.     if ((err==noErr)&&(*selStart>=*selEnd))
  630.         return icNoURLErr;
  631.     
  632.     err=PtrToXHand((Ptr)&(datap[*selStart]),urlh,(*selEnd)-(*selStart));
  633.     if (err==noErr)
  634.         err=StripReturns(urlh);
  635.     
  636.     if (err==noErr){
  637.         // strip any enclosing < >
  638.         char* buf;
  639.         long bsize=GetHandleSize(urlh);
  640.         SignedByte s=HGetState(urlh);
  641.         Boolean doTrim=false;
  642.         
  643.         HLock(urlh);
  644.         buf=(char*)(*urlh);
  645.         
  646.         if ((buf[0]=='<')&&(buf[bsize-1]=='>')){
  647.             doTrim=true;
  648.         }
  649.         
  650.         HSetState(urlh,s);
  651.         
  652.         if (doTrim){
  653.             SetHandleSize(urlh,bsize-1);
  654.             HUnlock(urlh);
  655.             // unlock before the munger call
  656.             Munger(urlh,0,(Ptr)0,1,(Ptr)-1,0);
  657.             HSetState(urlh,s);
  658.         }
  659.         
  660.         // trim off leading "\pURL:"
  661.         HLock(urlh);
  662.         if ((GetHandleSize(urlh)>tmp[0])&&(IUMagIDString(*urlh,&(tmp[1]),tmp[0],tmp[0])==0)){
  663.             HUnlock(urlh);
  664.             Munger(urlh,0,(Ptr)0,tmp[0],(Ptr)-1,0);
  665.         }
  666.         HSetState(urlh,s);
  667.         
  668.         // search for protocol
  669.         tmp[0]=1;tmp[1]=':';
  670.         HUnlock(urlh);
  671.         ndx=Munger(urlh,0,&(tmp[1]),1,(Ptr)0,0);
  672.         if ((ndx<0)||(ndx>255)){
  673.             // failed to find a colon in first 256 bytes,prepend "hint:" to url
  674.             if (hint[0]==0)
  675.                 err=icNoURLErr;
  676.             else {
  677.                 Munger(urlh,0,(Ptr)0,0,&(hint[1]),hint[0]);
  678.                 err=MemError();
  679.             }
  680.         }
  681.         HSetState(urlh,s);
  682.     }
  683.     return err;
  684. }
  685.  
  686. ICError ICRLaunchURL(ICRRecord* inst,StringPtr hint,Ptr data,long len,long* selStart,long* selEnd){
  687.     ICError err;
  688.     Handle urlh;
  689.     ICAppSpec helper;
  690.     Str255 scheme;
  691.     Str255 temp=kICHelper;
  692.     long junk_attr;
  693.     long size;
  694.     
  695.     urlh=NewHandle(0);
  696.     err=MemError();
  697.     
  698.     if (err==noErr)
  699.         err=ICRParseURL(inst,hint,data,len,selStart,selEnd,urlh);
  700.     else 
  701.         urlh=(Handle)0;
  702.     
  703.     if (err==noErr)
  704.         err=FindScheme(urlh,scheme);
  705.     
  706.     if (err==noErr){
  707.         size=sizeof(ICAppSpec);
  708.         BlockMoveData(scheme,(Ptr)&(temp[temp[0]+1]),scheme[0]);
  709.         temp[0]+=scheme[0];
  710.         err=ICRGetPref(inst,temp,&junk_attr,(Ptr)(&helper),&size);
  711.     }
  712.     
  713.     if (err==noErr)
  714.         err=LaunchURL(helper.fCreator,urlh);
  715.     
  716.     if (urlh!=(Handle)0)
  717.         DisposeHandle(urlh);
  718.     
  719.     return err;
  720. }
  721.  
  722. void UnpackCopyString(Ptr* p,StringPtr s){
  723.     short len;
  724.     
  725.     // calc the len of the current pascal string pointed to by p
  726.     len=((**p) & 0x00ff) +1;
  727.     
  728.     // copy the string in the buffer to s
  729.     BlockMoveData(*p,s,len);
  730.     
  731.     // move the pointer to the start of the next pascal string
  732.     *p=(Ptr)((*p)+len);
  733. }
  734.  
  735. // Internal Mapping Subs
  736. OSErr UnpackEntry(Handle entries,long pos,ICMapEntry* entry,long* user_length){
  737.     // WARNING: Depends very much on the exact format of ICMapEntry!
  738.     Ptr org,p;
  739.     long maxsize;
  740.     OSErr err=noErr;
  741.     
  742.     if ((entries==(Handle)0)||(*entries==(Ptr)0)||(pos<0)||(pos>GetHandleSize(entries)-6))
  743.         return paramErr;
  744.     
  745.     p=(Ptr)((*entries)+pos);
  746.     maxsize=GetHandleSize(entries);
  747.     org=p;
  748.     
  749.     BlockMoveData(p,(Ptr)entry,6);
  750.     
  751.     if ((entry->fixed_length!=ICmap_fixed_length)||(entry->fixed_length>entry->total_length)||(entry->total_length>maxsize))
  752.         return badExtResource;
  753.     
  754.     BlockMoveData(p,entry,entry->fixed_length);
  755.     p=(Ptr)(p+entry->fixed_length);
  756.     UnpackCopyString(&p,entry->extension);
  757.     UnpackCopyString(&p,entry->creator_app_name);
  758.     UnpackCopyString(&p,entry->post_app_name);
  759.     UnpackCopyString(&p,entry->MIME_type);
  760.     UnpackCopyString(&p,entry->entry_name);
  761.     
  762.     *user_length=entry->total_length-(p-org);
  763.     
  764.     return err;
  765. }
  766.  
  767. // a fast version of ICRGetEntry doesn't return all of the strings for the entry
  768. // WARNING: Depends very much on the exact format of ICMapEntry!
  769. OSErr FastGetEntry(Handle entries,long pos,ICMapEntry* entry){
  770.     Ptr org,p;
  771.     long maxsize;
  772.     OSErr err=noErr;
  773.     
  774.     if ((entries==(Handle)0)||(*entries==(Ptr)0)||(pos<0)||(pos>GetHandleSize(entries)-6))
  775.         return paramErr;
  776.     
  777.     p=(Ptr)((*entries)+pos);
  778.     maxsize=GetHandleSize(entries);
  779.     BlockMoveData(p,entry,6);
  780.     
  781.     if ((entry->fixed_length!=ICmap_fixed_length)||(entry->fixed_length>entry->total_length)||(entry->total_length>maxsize))
  782.         return badExtResource;
  783.     
  784.     BlockMoveData(p,entry,entry->fixed_length);
  785.     p=(Ptr)(p+entry->fixed_length);
  786.     BlockMoveData(p,entry->extension,(((*p)&0x00ff)+1));
  787.     return err;
  788. }
  789.  
  790. void PackCopyString(ICMapEntry* entry,Ptr p,StringPtr s){
  791.     
  792.     BlockMoveData(s,(Ptr)(p+entry->total_length),s[0]+1);
  793.     entry->total_length+=s[0]+1;
  794. }
  795.  
  796. void PackEntry(ICMapEntry* entry,Ptr p,long user_length){
  797.     Ptr a,b;
  798.     
  799.     entry->version=0;
  800.     
  801.     a=(Ptr)&(entry->extension);
  802.     b=(Ptr)entry;
  803.     
  804.     entry->fixed_length=a-b;
  805.     entry->total_length=entry->fixed_length;
  806.     
  807.     PackCopyString(entry,p,entry->extension);
  808.     PackCopyString(entry,p,entry->creator_app_name);
  809.     PackCopyString(entry,p,entry->post_app_name);
  810.     PackCopyString(entry,p,entry->MIME_type);
  811.     PackCopyString(entry,p,entry->entry_name);
  812.     
  813.     entry->total_length+=user_length;
  814.     
  815.     BlockMoveData(entry,p,entry->fixed_length);
  816. }
  817.  
  818. short GetShort(Ptr P){
  819.     unsigned char* p=(unsigned char*)P;
  820.     short val=0;
  821.     
  822.     val=p[0];
  823.     val <<= 8;
  824.     val+=p[1];
  825.     
  826.     return val;
  827. }
  828.  
  829. char UpCase(char ch){
  830.     
  831.     if ((ch>='a')&&(ch<='z'))
  832.         return (ch-'a')+'A';
  833.     
  834.     return ch;
  835. }
  836.  
  837. Boolean IsExtensionVar(StringPtr name,StringPtr ext){
  838.     short pn,pe;
  839.     
  840.     if (name[0]>=ext[0]){
  841.         pn=name[0]-ext[0]+1;
  842.         pe=1;
  843.         
  844.         while (pe<=ext[0]){
  845.             if (UpCase(name[pn])!=UpCase(ext[pe]))
  846.                 break;
  847.             
  848.             pn++;
  849.             pe++;
  850.         }
  851.         
  852.         return pe>ext[0];
  853.     }
  854.     return false;
  855. }
  856.  
  857. // Low Level Mapping Routines
  858.  
  859. ICError ICRCountMapEntries(ICRRecord* inst,Handle entries,long* count){
  860.     Ptr p;
  861.     long pos;
  862.     short size;
  863.     long hsize;
  864.     
  865.     if ((entries==(Handle)0)||(*entries==(Ptr)0))
  866.         return paramErr;
  867.     
  868.     p=*entries;
  869.     pos=0L;
  870.     *count=0;
  871.     hsize=GetHandleSize(entries);
  872.     while (pos<hsize){
  873.         size=GetShort(p); // extract the total_length value from the current pointer
  874.         pos+=size; // add it to the pos offset
  875.         p+=size; // add it to the pointer
  876.         (*count)++; // increment the count
  877.     }
  878.     
  879.     return noErr;
  880. }
  881.  
  882. ICError ICRGetIndMapEntry(ICRRecord* inst,Handle entries,long ndx,long* pos,ICMapEntry* entry){
  883.     ICError err;
  884.     Ptr p;
  885.     long i;
  886.     short size;
  887.     long hsize;
  888.     
  889.     if ((entries==(Handle)0)||(*entries==(Ptr)0)||(ndx<0))
  890.         return paramErr;
  891.     
  892.     p=(Ptr)*entries;
  893.     *pos=0;
  894.     hsize=GetHandleSize(entries);
  895.     
  896.     while ((ndx>1)&&(*pos<hsize)){
  897.         size=GetShort(p); // extract the total_length value from the current pointer
  898.         *pos+=size; // add the size to the pos offset
  899.         p+=size; // add the size to the pointer
  900.         ndx--; // decrease the index for the entry
  901.     }
  902.     
  903.     return ICRGetMapEntry(inst,entries,*pos,entry);
  904. }
  905.  
  906. ICError ICRGetMapEntry(ICRRecord* inst,Handle entries,long pos,ICMapEntry* entry){
  907.     ICError err;
  908.     long user_length;
  909.     
  910.     if ((entries==(Handle)0)||(*entries==(Ptr)0)||(pos<0)||(pos>GetHandleSize(entries)))
  911.         return paramErr;
  912.     
  913.     return UnpackEntry(entries,pos,entry,&user_length);
  914. }
  915.  
  916. ICError ICRSetMapEntry(ICRRecord* inst,Handle entries,long pos,ICMapEntry* entry){
  917.     ICError err;
  918.     ICMapEntry e,oldentry;
  919.     long user_length,source_length;
  920.     
  921.     if ((entries==(Handle)0)||(*entries==(Ptr)0)||(pos<0)||(pos>GetHandleSize(entries)))
  922.         return paramErr;
  923.     
  924.     err=UnpackEntry(entries,pos,&oldentry,&user_length);
  925.     
  926.     if (err==noErr){
  927.         PackEntry(entry,(Ptr)&e,user_length);
  928.         source_length=oldentry.total_length-user_length;
  929.         
  930.         if (user_length<8){ // hack to remove alignment bytes from previous version
  931.             source_length=oldentry.total_length;
  932.             e.total_length=e.total_length-user_length;
  933.             user_length=0;
  934.         }
  935.         Munger(entries,pos,(Ptr)0,source_length,&e,e.total_length-user_length);
  936.         err=MemError();
  937.     }
  938.     
  939.     return err;
  940. }
  941.  
  942. ICError ICRDeleteMapEntry(ICRRecord* inst,Handle entries,long pos){
  943.     ICError err;
  944.     ICMapEntry entry;
  945.     long user_length;
  946.     
  947.     if ((entries==(Handle)0)||(*entries==(Ptr)0)||(pos<0)||(pos>=GetHandleSize(entries)))
  948.         return paramErr;
  949.     
  950.     err=UnpackEntry(entries,pos,&entry,&user_length);
  951.     
  952.     if (err==noErr){
  953.         Munger(entries,pos,(Ptr)0,entry.total_length,(Ptr)-1,0);
  954.         err=MemError();
  955.     }
  956.     
  957.     return err;
  958. }
  959.  
  960. ICError ICRAddMapEntry(ICRRecord* inst,Handle entries,ICMapEntry* entry){
  961.     ICError err;
  962.     ICMapEntry tmp_entry;
  963.     
  964.     if ((entries==(Handle)0)||(*entries==(Ptr)0))
  965.         return paramErr;
  966.     
  967.     PackEntry(entry,(Ptr)&tmp_entry,0);
  968.     
  969.     return PtrAndHand(&tmp_entry,entries,entry->total_length);
  970. }
  971.  
  972. // High Level Mapping Subs
  973.  
  974. ICError ICRMapEntriesFilename(ICRRecord* inst,Handle entries,StringPtr filename,ICMapEntry* entry){
  975.     // Implementation lifted directly from Space Aliens
  976.     ICError err;
  977.     short longest_len;
  978.     long posndx,found_pos;
  979.     
  980.     if ((entries==(Handle)0)||(*entries==(Ptr)0)||(filename[0]==0))
  981.         return paramErr;
  982.     
  983.     // loop through the entries
  984.     // looking for the longest match
  985.     
  986.     longest_len=0;
  987.     posndx=0;
  988.     
  989.     while (FastGetEntry(entries,posndx,entry)==noErr){
  990.         // the entry matches if not_incoming flag bit is clear,
  991.         // it's longer than the previous match, it's longer than the filename,
  992.         // and it matches the last N chars of the filename.
  993.         
  994.         if ((entry->extension[0]>longest_len)&&(!(entry->flags&ICmap_not_incoming_mask))&&(IsExtensionVar(filename,entry->extension))){
  995.             // record the new longest entry
  996.             found_pos=posndx;
  997.             longest_len=entry->extension[0];
  998.         }
  999.         // increment posndx so that we get the next entry the next time around the loop
  1000.         posndx+=entry->total_length;
  1001.     }
  1002.     
  1003.     if (longest_len==0)
  1004.         return icPrefNotFoundErr;
  1005.     
  1006.     return ICRGetMapEntry(inst,entries,found_pos,entry);
  1007. }
  1008.  
  1009. ICError ICRMapEntriesTypeCreator(ICRRecord* inst,Handle entries,OSType fType,OSType fCreator,StringPtr filename,ICMapEntry* entry){
  1010.     ICError err;
  1011.     long posndx,found_pos,match_weight,best_weight;
  1012.     
  1013.     if ((entries==(Handle)0)||(*entries==(Ptr)0))
  1014.         return paramErr;
  1015.     
  1016.     posndx=0L;
  1017.     best_weight=-1L;
  1018.     
  1019.     while (FastGetEntry(entries,posndx,entry)==noErr){
  1020.         if (!(entry->flags&ICmap_not_outgoing_mask)){
  1021.             if (entry->file_type==fType){
  1022.                 match_weight=entry->file_creator==fCreator;
  1023.                 if (IsExtensionVar(filename,entry->extension)){
  1024.                     match_weight+=2*(entry->extension[0]);
  1025.                 }
  1026.                 if (match_weight>best_weight){
  1027.                     // record the new longest entry
  1028.                     found_pos=posndx;
  1029.                     best_weight=match_weight;
  1030.                 }
  1031.             }
  1032.         }
  1033.         posndx+=entry->total_length;
  1034.     }
  1035.     
  1036.     if (best_weight==-1)
  1037.         return icPrefNotFoundErr;
  1038.     
  1039.     return ICRGetMapEntry(inst,entries,found_pos,entry);
  1040. }
  1041.  
  1042. // High Level Mapping Routines
  1043.  
  1044. ICError ICRMapFilename(ICRRecord* inst,StringPtr filename,ICMapEntry* entry){
  1045.     ICError err;
  1046.     Handle entries;
  1047.     ICAttr junk_attr;
  1048.     
  1049.     if (filename[0]==0)
  1050.         return paramErr;
  1051.     
  1052.     err=ICRGetPrefHandle(inst,kICMapping,&junk_attr,&entries);
  1053.     if (err==noErr){
  1054.         err=ICRMapEntriesFilename(inst,entries,filename,entry);
  1055.         DisposeHandle(entries);
  1056.     }
  1057.     
  1058.     return err;
  1059. }
  1060.  
  1061. ICError ICRMapTypeCreator(ICRRecord* inst,OSType fType,OSType fCreator,StringPtr filename,ICMapEntry* entry){
  1062.     ICError err;
  1063.     Handle entries;
  1064.     ICAttr junk_attr;
  1065.     
  1066.     err=ICRGetPrefHandle(inst,kICMapping,&junk_attr,&entries);
  1067.     if (err==noErr){
  1068.         err=ICRMapEntriesTypeCreator(inst,entries,fType,fCreator,filename,entry);
  1069.         DisposeHandle(entries);
  1070.     }
  1071.     
  1072.     return err;
  1073. }
  1074.  
  1075.  
  1076.  
  1077.  
  1078.  
  1079.  
  1080.  
  1081.  
  1082.  
  1083.  
  1084.